package com.itheima.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Slf4j
@Component
//@Aspect // 表示这是一个切面类
public class MyAspect1 {

    // 切入点表达式抽取

    /**
     * 切入点表达式的书写建议 ---> 尽可能的在满足需求的前提下, 缩小切入点的匹配范围.
     */
    //@Pointcut("execution(* com.itheima.service.impl.*.list(..))")
    //@Pointcut("execution(public com.itheima.pojo.Dept com.itheima.service.impl.DeptServiceImpl.getById(java.lang.Integer))")
    //@Pointcut("execution(com.itheima.pojo.Dept com.itheima.service.impl.DeptServiceImpl.getById(java.lang.Integer))")
    //@Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.getById(java.lang.Integer))")
    //@Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.getById(*))")
    //@Pointcut("execution(* com.itheima.service.impl.*.*(*))")
    //@Pointcut("execution(* com.itheima.*.impl.*.*(*))")
    //@Pointcut("execution(* com.itheima.*.impl.*.get*(*))")
    //@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
    //@Pointcut("execution(* com.itheima.service.*.*(..))")
    //@Pointcut("execution(* com..impl.*.*(..))")

    //@Pointcut("execution(* *(..))") //禁用
    //@Pointcut("execution(* com.itheima.service.impl.DeptServiceImpl.list(..)) || " +
    //          "execution(* com.itheima.service.impl.DeptServiceImpl.save(..)) ||" +
    //          "execution(* com.itheima.service.impl.DeptServiceImpl.delete(..)) ")

    @Pointcut("@annotation(com.itheima.annotation.Log)") //匹配的是被这个注解标识的方法
    private void hello() {}

    // 前置通知 - 原始方法运行前执行
    @Before("hello()")
    public void before() {
        log.info("前置通知 ... before");
    }

    // 环绕通知 - 原始方法运行前 和 运行后执行
    @Around("hello()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("环绕通知 ... around before");
        // 运行原始方法
        Object result = pjp.proceed();
        log.info("环绕通知 ... around after");
        return result;
    }

    // 后置通知 - 原始方法运行后执行 (无论原始方法运行是否出现异常, 都会执行)
    @After("hello()")
    public void after() {
        log.info("后置通知 ... after");
    }

    // 后置通知 - 原始方法运行后执行, 正常执行返回才执行 (原始方法运行出现异常, 则不会执行)
    @AfterReturning("hello()")
    public void afterReturning() {
        log.info("afterReturning .... ");
    }

    // 异常通知 - 原始方法运行后执行, 原始方法运行出现异常才执行
    @AfterThrowing("hello()")
    public void afterThrowing() {
        log.info("afterThrowing .... ");
    }
}
